﻿using EventNext;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Test
{
    [Service(typeof(IChatService))]
    [Description("lalalla")]
    public partial class ChatService : ActorState, IChatService
    {
        public async Task<string> Query(string id, int seconds)
        {
            Console.WriteLine($"{Identity.Name} Query data {id} in {seconds}s. at {DateTime.Now.ToString("HH:mm:ss.fff")}");
            await Task.Delay(seconds * 1000);
            string message = $"{Identity.Name} {id} returned in {seconds}s. at {DateTime.Now.ToString("HH:mm:ss.fff")}.Token:{Token}";
            Console.WriteLine(message);
            return message;
        }

    }


    partial class ChatService
    {
        static readonly ConcurrentDictionary<string, IIdentity> sessions = new ConcurrentDictionary<string, IIdentity>();
        public ChatService()
        {

        }
        protected IIdentity Identity { get; private set; }
    }


    partial class ChatService
    {
        public async Task Say(string someOne, string message)
        {
            await Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine($"{Identity?.Name} {someOne} said:{message}");
            });
        }


        public async Task<string> SignIn(string id)
        {
            return await Task.Run<string>(() =>
            {
                string token = ActorID;
                if (!sessions.ContainsKey(token))
                {
                    IIdentity identity = new AppUser()
                    {
                        AuthenticationType = id
                           ,
                        IsAuthenticated = true
                           ,
                        Name = DateTime.Now.ToString("HH:mm:ss.fff")
                    };
                    sessions.AddOrUpdate(token, identity, (x, y) => identity);
                    this.Identity = identity;
                    return $"{id} signed in success!{ActorID}";
                }
                return $"{Identity.Name} {id} has already signed in!{ActorID}";
            });
        }

        public async Task SayTo(string someOne, string message, string to)
        {
            await Task.Run(() => Console.WriteLine($"{Identity.Name} {someOne} said to {to}:{message}"));
        }

        public async Task<string> Delay(int seconds)
        {
            string token = this.ActorID;
            return await Task.Run<string>(() =>
            {
                //SynchronizationContext context = SynchronizationContext.Current;
                //context.Post(new SendOrPostCallback((target) => {

                //}),new {
                //    Token= token
                //});
                return MyBLL.Delay(seconds, token);
            });

        }

    }

    class MyBLL
    {
        [ThreadStatic]
        static string MyToken = null;

        public static string Delay(int seconds, string token)
        {
            if (MyToken == null) MyToken = token;
            Thread.Sleep(seconds * 1000);
            return $"{token} is {MyToken} delayed {seconds}s.";
        }
    }
}
